package com.example.manager.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.common.exception.GuiguException;
import com.example.common.helper.JwtHelper;
import com.example.manager.mapper.SysUserMapper;
import com.example.manager.mapper.SysUserRoleMapper;
import com.example.manager.service.SysUserService;
import com.example.model.constant.RedisConstant;
import com.example.model.dto.system.LoginDto;
import com.example.model.dto.system.SysUserDto;
import com.example.model.entity.system.SysRoleUser;
import com.example.model.entity.system.SysUser;
import com.example.model.vo.common.ResultCodeEnum;
import com.example.model.vo.system.LoginVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.concurrent.TimeUnit;


@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {

    @Autowired
    private SysUserMapper sysUserMapper;


    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;

    //用户登录
    @Override
    public LoginVo login(LoginDto loginDto) {
        LoginVo loginVo = new LoginVo();
        // 1.获取提交用户名，loginDto获取到
        String userName = loginDto.getUsername();
        //用户输入的验证码
        String captcha = loginDto.getCaptcha();
        //2.redis中存的值
        String codeKey = loginDto.getCodeKey();

        String code = redisTemplate.opsForValue().get(RedisConstant.USER_VALIDATE + codeKey);

        if (code == null || !code.equalsIgnoreCase(captcha)) {
            throw new GuiguException(ResultCodeEnum.VALIDATECODE_ERROR);
        }
        redisTemplate.delete(RedisConstant.USER_VALIDATE + codeKey);

        //2.根据用户名查询数据库表 sys_user表
        LambdaQueryWrapper<SysUser> sysUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
        SysUser sysUser = sysUserMapper.selectOne(sysUserLambdaQueryWrapper.eq(SysUser::getUsername, userName));

        //3.如果根据用户名查不到对应数据，用户不存在，返回错误信息
        if(sysUser == null){
            throw new GuiguException(ResultCodeEnum.USER_NOT_EXIST);
        }
        //4.如果根据用户名查询到用户信息，用户存在
        //5.获取输入的密码，比较输入的密码和数据库的密码是否一致
        //5.1 数据库的密码是加密的，所以先加密然后再进行比较
        String md5Password = DigestUtils.md5DigestAsHex(loginDto.getPassword().getBytes());

        //6.如果密码一致，登录成功，如果密码不一致登录失败
        if (!sysUser.getPassword().equals(md5Password)) {
            throw new GuiguException(ResultCodeEnum.LOGIN_ERROR);
        }
        //7.登录成功，生成用户唯一标识token
        String token = JwtHelper.createToken(sysUser.getId(), sysUser.getUsername());

        String key = RedisConstant.USER_LOGIN + token;
        //8.把token存入redis里面
        redisTemplate.opsForValue().set(key,token,7, TimeUnit.DAYS);
        //9.返回loginVO对象

        loginVo.setToken(token);

        return loginVo;
    }


    //用户退出
    @Override
    public void logout(String token) {
        redisTemplate.delete(RedisConstant.USER_LOGIN + token);
    }

    @Override
    public SysUser getUserInfo(HttpServletRequest request) {

        SysUser sysUser = new SysUser();
        //1.从请求头中获取到token,
        String token = request.getHeader("token");
        if(token == null){
            throw new GuiguException(ResultCodeEnum.LOGIN_AUTH);
        }
        if(token != null){
            //2.从redis中获取到token
            if(token.startsWith("Bearer")){
                token = token.replace("Bearer ","");
            }
            String key = RedisConstant.USER_LOGIN + token;
            String redisToken = redisTemplate.opsForValue().get(key);
            if(redisToken == null){
                throw new GuiguException(ResultCodeEnum.LOGIN_AUTH);
            }
            Long userId = JwtHelper.getUserId(redisToken);

            sysUser = sysUserMapper.selectOne(new LambdaQueryWrapper<SysUser>()
                    .eq(SysUser::getId, userId));
        }
        return sysUser;
    }

    @Override
    public Page<SysUser> findAllSysUser(SysUserDto sysUserDto) {
        Page<SysUser> sysUserPage = new Page<>(sysUserDto.getPageNum(), sysUserDto.getPageSize());

        LambdaQueryWrapper<SysUser> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNoneEmpty(sysUserDto.getKeyword())){
            lambdaQueryWrapper
                    .like(SysUser::getUsername, sysUserDto.getKeyword())
                    .or()
                    .like(SysUser::getName, sysUserDto.getKeyword())
                    .or()
                    .like(SysUser::getPhone, sysUserDto.getKeyword());
        }
        if (StringUtils.isNoneEmpty(sysUserDto.getCreateTimeBegin()) && StringUtils.isNoneEmpty(sysUserDto.getCreateTimeEnd())){
            lambdaQueryWrapper.ge(SysUser::getCreateTime, sysUserDto.getCreateTimeBegin())
                    .le(SysUser::getCreateTime, sysUserDto.getCreateTimeEnd());
        }
        Page page = sysUserMapper.selectPage(sysUserPage, lambdaQueryWrapper);


        return page;
    }

    @Override
    public void deleteBatch(List<Long> idList) {
        //如果用户下面有角色必须先删除角色
       for (Long id : idList){
           Integer integer = sysUserRoleMapper.selectCount(new LambdaQueryWrapper<SysRoleUser>()
                   .eq(SysRoleUser::getUserId, id));
           if (integer>0){
               throw new GuiguException(ResultCodeEnum.NODE_ROLE);
           }
           sysUserMapper.delete(id);
       }
    }

    @Override
    public void saveUser(SysUser sysUser) {

    }

    @Override
    public void updatePassword(SysUser sysUser) {

    }

}
